package com.dc.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dc.common.ResponseResultVO;
import com.dc.entity.*;
import com.dc.entity.ro.SysResourceRO;
import com.dc.entity.vo.MenuBtnVO;
import com.dc.mapper.*;
import com.dc.ro.PageRO;
import com.dc.service.SysResourceService;
import com.dc.util.ListBeanUtils;
import com.dc.util.SnowflakeIdWorker;
import com.dc.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统菜单接口实现
 */
@Service
@Slf4j
public class SysResourceServiceImpl implements SysResourceService {

    @Resource
    private SysResourceMapper sysResourceMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private SysRoleResourceMapper sysRoleResourceMapper;

    @Resource
    private SysRoleMapper roleMapper;


    @Override
    public ResponseResultVO insert(SysResourceRO sysResource) {
        if (StrUtil.isBlank(sysResource.getNameCn())) {
            return ResponseResultVO.failResult("菜单名称不能为空");
        }

        if (null == (sysResource.getResourceType())) {
            return ResponseResultVO.failResult("菜单类型不能为空");
        }

        if (null == sysResource.getParentId()) {
            sysResource.setParentId(0L);
        }

        if (StrUtil.isBlank(sysResource.getNameEn())) {
            sysResource.setNameEn(sysResource.getNameCn());
        }

        SysResource sysResourceDTO = new SysResource();
        BeanUtils.copyProperties(sysResource, sysResourceDTO);
        sysResourceDTO.setId(SnowflakeIdWorker.generateId());

        int i = sysResourceMapper.insert(sysResourceDTO);

        if (i <= 0) {
            return ResponseResultVO.failResult("新增失败");
        }

        return ResponseResultVO.successResult("新增成功");
    }

    @Override
    public ResponseResultVO update(SysResourceRO sysResource) {
        if (sysResource.getId() == null) {
            return ResponseResultVO.failResult("菜单id不能为空");
        }

        SysResource oldResource = this.sysResourceMapper.selectById(sysResource.getId());
        if (oldResource == null) {
            return ResponseResultVO.failResult("菜单不存在");
        }
        SysResource sysResourceDTO = new SysResource();
        BeanUtils.copyProperties(sysResource, sysResourceDTO);
        sysResourceDTO.setId(sysResource.getId());

        return ResponseResultVO.updateResult(sysResourceMapper.updateById(sysResourceDTO));
    }


    @Override
    public ResponseResultVO delete(String id) {
        int num = this.sysResourceMapper.deleteById(id);
        if (num <= 0) {
            return ResponseResultVO.failResult("失败");
        }

        return ResponseResultVO.successResult("删除成功");
    }


    @Override
    public ResponseResultVO selectSysResourceList(PageRO pageRO) {
        Page page = new Page<Map<String, Object>>(pageRO.getCurrentPage(), pageRO.getPageSize());
        return ResponseResultVO.resultList(sysResourceMapper.selectPage(page, new QueryWrapper()), pageRO);
    }

    @Override
    public ResponseResultVO selectTreeList(SysResourceRO ro) {

        QueryWrapper<SysResource> queryWrapper = new QueryWrapper();
        if (null != (ro.getId())) {
            queryWrapper.eq("id", ro.getId());
        }

        if (null != (ro.getParentId())) {
            // queryWrapper.eq()
        }

        if (StrUtil.isNotBlank(ro.getNameCn())) {
            queryWrapper.eq("name_cn", ro.getNameCn());
        }

        if (StrUtil.isNotBlank(ro.getNameEn())) {
            queryWrapper.eq("name_en", ro.getNameEn());
        }

        if (StrUtil.isNotBlank(ro.getPermission())) {
            queryWrapper.eq("permission", ro.getPermission());
        }

        List<SysResource> list = sysResourceMapper.selectList(queryWrapper);

        List<SysResource> treeList = this.listToTreeList(list);

        return ResponseResultVO.successResult(treeList);
    }

    @Override
    public ResponseResultVO menuInit() {
        SysUser sysUser = sysUserMapper.selectById(UserUtil.getUserId());

        if (sysUser.getIsSuper() != null && sysUser.getIsSuper() == 1) {
            // 超级管理员查询拥有所有菜单权限
            QueryWrapper<SysResource> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("is_delete", 0);
//            queryWrapper.eq("resource_type", 0);
            queryWrapper.orderByAsc("sort_no");
            List<SysResource> sysResources = sysResourceMapper.selectList(queryWrapper);
            // 将集合转换成树形集合(前端需要的数据格式)
            List<SysResource> treeList = this.listToTreeList(sysResources);
            return ResponseResultVO.successResult(treeList);
        }

        //查询当前用户的菜单
        List<SysResource> list = getSysResourceDTOS(null, null, -1);

        List<Long> keyList = new ArrayList<>();
        for (SysResource sysResource : list) {
            keyList.add(sysResource.getId());
        }
        List<SysResource> newList = new ArrayList<>();
        for (SysResource sysResource : list) {
            // 递归查询到顶级节点
            this.findParentMenu(sysResource, keyList, newList);
        }
        if (!CollectionUtils.isEmpty(newList)) {
            list.addAll(newList);
        }
        // 将集合转换成树形集合(前端需要的数据格式)
        List<SysResource> treeList = this.listToTreeList(list);

        return ResponseResultVO.successResult(treeList);
    }

    /**
     * 查询当前用户的菜单
     *
     * @param menuId
     * @param menuUrl
     * @param type    1 表示查询按钮  -1 表示所有
     * @return
     */
    private List<SysResource> getSysResourceDTOS(Long menuId, String menuUrl, int type) {
        //查询用户角色
        QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", UserUtil.getUserId());
        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(wrapper);
        List<SysRole> sysRoles = new ArrayList<>();
        if (!CollectionUtils.isEmpty(sysUserRoles)) {
            sysRoles = roleMapper.selectList(new QueryWrapper<SysRole>().lambda().in(SysRole::getId, sysUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList()))
                    .eq(SysRole::getIsEnable, 0));
        }

        //角色查询权限
        List<Long> res = new ArrayList<>();
        for (SysRole sysRole : sysRoles) {
            res.add(sysRole.getId());
        }
        QueryWrapper<SysRoleResource> queryWrapper = new QueryWrapper();

        List<SysRoleResource> sysRoleResourceList = null;
        queryWrapper.in("role_id", res);
        if (CollectionUtils.isEmpty(res)) {
            sysRoleResourceList = new ArrayList<>();
        } else {
            sysRoleResourceList = sysRoleResourceMapper.selectList(queryWrapper);
        }

        //权限查菜单
        QueryWrapper<SysResource> resourceDTOQueryWrapper = new QueryWrapper<>();
        List<Long> resources = new ArrayList<>();
        for (SysRoleResource sysRoleResource : sysRoleResourceList) {
            resources.add(sysRoleResource.getResourceId());
        }
        if (!CollectionUtils.isEmpty(resources)) {
            resourceDTOQueryWrapper.in("id", resources);
        } else {
            resourceDTOQueryWrapper.eq("id", "-1");
        }

        if (null != menuId) {
            resourceDTOQueryWrapper.eq("id", menuId);
        }

        if (StrUtil.isNotBlank(menuUrl)) {
            resourceDTOQueryWrapper.eq("url", menuUrl);
        }

        if (type != -1) {
            resourceDTOQueryWrapper.eq("resource_type", type);
        }
        resourceDTOQueryWrapper.eq("is_delete", 0);
        return sysResourceMapper.selectList(resourceDTOQueryWrapper);
    }

    @Override
    public ResponseResultVO selectMenuBtnList() {
        SysUser sysUser = sysUserMapper.selectById(UserUtil.getUserId());
        List<SysResource> sysResources = null;
        if (sysUser.getIsSuper() != null && sysUser.getIsSuper() == 1) {
            sysResources = sysResourceMapper.selectList(new QueryWrapper<SysResource>().lambda().eq(SysResource::getResourceType, 2));
        } else {
            List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, sysUser.getId()));
            if (!CollectionUtils.isEmpty(sysUserRoles)) {
                List<SysRoleResource> sysRoleResources = sysRoleResourceMapper.selectList(new QueryWrapper<SysRoleResource>().lambda().in(SysRoleResource::getRoleId, sysUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList())));
                if (!CollectionUtils.isEmpty(sysRoleResources)) {
                    Set<Long> resourceIds = sysRoleResources.stream().map(SysRoleResource::getResourceId).collect(Collectors.toSet());
                    if (!CollectionUtils.isEmpty(resourceIds)) {
                        sysResources = sysResourceMapper.selectList(new QueryWrapper<SysResource>().lambda().in(SysResource::getId, resourceIds).eq(SysResource::getResourceType, 2));

                    }
                }
            }
        }
        List<MenuBtnVO> menuBtnVOS = ListBeanUtils.listCopyMapper(sysResources, SysResource.class, MenuBtnVO.class);
        return ResponseResultVO.successResult(menuBtnVOS);
    }


    /**
     * 递归查询上级菜单，一直查到一级菜单
     *
     * @param menuVO   需要递归查询的菜单对象
     * @param keyList  已查询到的菜单id集合
     * @param menuList 递归查询到的数据存放集合
     */
    private void findParentMenu(SysResource menuVO, List<Long> keyList, List<SysResource> menuList) {
        if (null == menuVO.getParentId() || 0 == menuVO.getParentId() || keyList.contains(menuVO.getParentId())) {
            // 一级节点、已存在节点 则跳过
            return;
        }
        SysResource menu = this.sysResourceMapper.selectById(menuVO.getParentId());
        if (menu != null) {
            menuList.add(menu);
            keyList.add(menuVO.getParentId());

            // 递归查询到顶级节点
            this.findParentMenu(menu, keyList, menuList);
        }
    }


    /**
     * 将list转换成树形结构集合
     *
     * @param list 需要转化的数据
     * @return 转换后的树形结构集合
     */
    @Override
    public List<SysResource> listToTreeList(List<SysResource> list) {
        List<SysResource> treeList = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return treeList;
        }
        /*
         * 先对集合排序
         * 排序后，最终的树形集合、各节点下的子节点集合，都会与初始集合排序规则一致
         */
        Comparator<SysResource> ageComparator = (o1, o2) -> o1.getSortNo().compareTo(o2.getSortNo());
        // 按配置的顺序取值
        list.sort(ageComparator);

        Map<Long, SysResource> map = new HashMap<>();
        // 将菜单集合数据存放到map集合中，key为菜单id，后续判断父节点用
        for (SysResource menuVO : list) {
            map.put(menuVO.getId(), menuVO);
            // 将一级节点添加到树形集合中
            if (null == menuVO.getParentId() || 0 == menuVO.getParentId()) {
                treeList.add(menuVO);
            }
        }
        // 遍历结果集
        for (SysResource menuVO : list) {
            if (null == menuVO.getParentId() || 0 == menuVO.getParentId()) {
                // 跳过一级节点
                continue;
            }
            // 判断父节点是否存在
            SysResource parentMenu = map.get(menuVO.getParentId());
            if (parentMenu != null) {
                // 父节点存在，则将该节点添加到父节点的子节点集合中
                parentMenu.getChildren().add(menuVO);
            }
        }
        return treeList;
    }

    @Override
    public ResponseResultVO selectSysResourceByParentId(Long parentId) {
        if (parentId == null) {
            parentId = 0L;
        }
        QueryWrapper<SysResource> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentId);
        queryWrapper.orderByAsc("sort_no");
        List<SysResource> sysResources = sysResourceMapper.selectList(queryWrapper);
        return ResponseResultVO.successResult(sysResources);
    }


}
